# Defining a custom SplitStrategy

import { Callout } from 'nextra/components';

<Callout type="warning">
	Sui Owned Object Pools (SuiOOP) will likely be replaced by
	[`ParallelTransactionExecutor`](../executors#paralleltransactionexecutor) from
	`@mysten/sui/transactions`

    Sui Owned Object Pools (SuiOOP) is a beta library. Enhancements and changes are likely during
    development.

</Callout>

The prior example does not define a split strategy explicitly, so it uses the
`DefaultSplitStrategy`.

This default split strategy only selects enough gas coins (coins of type
`0x2::coin::Coin<0x2::sui::SUI>`) from the `mainPool` that their sum of balances surpasses a minimum
threshold, and creates a new worker pool only containing these gas coins.

It fulfils the minimum requirement needed for a transaction to be executed, as the client should
always be able to pay for the gas of the transaction.

However, in more complex scenarios, you might want to define your own split strategy.

Assume that you want to execute multiple transactions that transfer an object of type `CapyNFT`,
each to a different recipient.

For this to work, the `ExecutorServiceHandler` needs to split the `mainPool` in a way such that
every worker:

- Contains at least one `CapyNFT` object.
- Contains at least a coin (or set of coins) with a total balance enough to pay for the gas of the
  transaction.

To do this, you have to implement the `SplitStrategy` interface. In detail:

```ts
class MyCustomSplitStrategy implements SplitStrategy {
	private capyIncluded = false;
	private balanceSoFar = 0;
	private readonly minimumBalance;

	public pred(obj: PoolObject | undefined) {
		if (!obj) throw new Error('No object found!.');
		// If each requirement is fulfilled then terminate the split by returning null
		// This stops the split process and the worker pool is created
		const terminateWhen = this.balanceSoFar >= this.minimumBalance && this.capyIncluded;
		if (terminateWhen) {
			return null;
		}
		// If a CapyNFT object is not already included, and the object is a CapyNFT, then include it
		if (!capyIncluded && obj.type.includes('CapyNFT')) {
			this.capyIncluded = true;
			return true;
		}
		// If the object is a coin and coins are still needed, then include it to the new pool
		if (this.balanceSoFar >= this.minimumBalance && isCoin(obj.type)) {
			this.balanceSoFar += obj.balance ?? 0;
			return true;
		} else {
			return false;
		}
	}
	// This function is called during the split process to check if the split was successful
	public succeeded() {
		return this.balanceSoFar >= this.minimumBalance && this.adminCapIncluded;
	}
}
```

You can find more examples of split strategies (including an admin cap inclusion case) in the
[`splitStrategies.ts` file](https://github.com/MystenLabs/Sui_Owned_Object_Pools/blob/main/src/splitStrategies.ts).
